// 本地认证策略定义
// 使用 passport-local 来处理用户注册和登录
import { Strategy } from 'passport-local';

import { PassportStrategy } from '@nestjs/passport'; // NestJS 的 Passport.js 封装库。Passport.js 是一个 Node.js 的身份验证中间件
import { Request } from 'express';
import { Injectable } from '@nestjs/common';
import { ContextIdFactory, ModuleRef } from '@nestjs/core'; // 用于在NestJS的请求处理上下文中解析依赖项
import { BusinessException } from '@/common';
import { AuthService } from '../auth.service';
@Injectable() // 将LocalStrategy类标记为NestJS的依赖注入系统的一部分，使其能够自动注入依赖项

// 通过PassportStrategy装饰器工厂和Strategy类，将LocalStrategy类转换为NestJS可识别的Passport策略
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private moduleRef: ModuleRef) {
    // 调用super方法初始化基类的配置, 在validate方法中会接收到请求对象（request）作为第一个参数
    super({
      passReqToCallback: true
    });
  }

  // 验证方法
  async validate(
    request: Request,
    username: string,
    password: string
  ): Promise<any> {
    console.log('登录策略', request.body)
    const body = request.body;
    // 从request.body中获取验证码（code），如果没有提供验证码，则抛出BusinessException异常
    if (!body?.code) {
      throw new BusinessException({
        code: 400,
        message: '请输入验证码'
      });
    }
    // NestJS的模块引用（ModuleRef）功能，允许在运行时动态地解析依赖项
    // 使用ContextIdFactory.getByRequest(request)获取当前请求的上下文ID
    const contextId = ContextIdFactory.getByRequest(request);

    // 通过this.moduleRef.resolve()在特定上下文中解析AuthService的实例
    const authService = await this.moduleRef.resolve(
      AuthService,
      contextId
    );



    // 从请求中获取日志信息（loggerInfo）和会话对象（session）
    // const loggerInfo = request.loggerInfo;
    const session = request.session;

    // 将用户名、密码、验证码和会话中的验证码ID作为参数传递给managerService.validateUser方法进行用户验证
    const user = await authService.validateAccount({
      username,
      password,
      code: body.code,
      codeId: session['codeId']
    },);
 

    // 如果用户验证失败（即validateAccount返回null或undefined），则抛出BusinessException异常，提示登录失败
    if (!user) {
      throw new BusinessException({
        code: 400,
        message: '登录失败，请检查登录信息（本地策略）',
      });
    }
    // 如果用户验证成功，则返回用户信息
    return user;
  }
}
